package com.eclipse.training;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

import com.eclipse.training.listeners.TableDragSourceListener;
import com.eclipse.training.listeners.TableDropAdapter;
import com.eclipse.training.listeners.TreeSelectionChangeListener;
import com.eclipse.training.model.Universe;
import com.eclipse.training.ui.ElementsArrayDataTransfer;
import com.eclipse.training.ui.TableLabelProvider;
import com.eclipse.training.ui.TreeSorter;
import com.eclipse.training.ui.TreeVoidFilter;
import com.eclipse.training.ui.UniverseDecoratorLabelProvider;
import com.eclipse.training.ui.UniverseTreeContentProvider;
import com.eclipse.training.ui.UniverseTreeLabelProvider;

public class Main {

	private static TreeViewer treeViewer;
	private static TableViewer tableViewer;
	private static TreeVoidFilter filter = new TreeVoidFilter();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);

		shell.setLayout(new GridLayout());
		shell.setSize(600, 400);

		shell.setText("Universe Model");

		/*
		 * Create shell content
		 */
		createToolBar(shell);
		createContent(shell);

		shell.open();

		while (!shell.isDisposed()) {
			/*
			 * Reads an event from the operating system's event queue,
			 * dispatches it appropriately, and returns true if there is
			 * potentially more work to do, or false if the caller can sleep
			 * until another event is placed on the event queue.
			 */
			if (!display.readAndDispatch()) {
				/*
				 * If no more entries in the event queue
				 */
				display.sleep();
			}
		}

		display.dispose();
	}

	private static void createContent(Shell shell) {
		SashForm sash = new SashForm(shell, SWT.NONE);

		/*
		 * Set the layout
		 */
		sash.setLayout(new GridLayout());
		sash.setLayoutData(new GridData(GridData.FILL_BOTH));

		/*
		 * Create the viewers in the shell
		 */
		createViewers(sash);

		/*
		 * Set the weights of the sash form
		 */
		sash.setWeights(new int[] { 2, 1 });
		sash.pack();
	}

	private static void createViewers(SashForm sash) {

		/*
		 * Create the tree viewer to display the universe tree
		 */
		treeViewer = new TreeViewer(sash, SWT.SINGLE | SWT.H_SCROLL
				| SWT.V_SCROLL);

		treeViewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));

		/*
		 * Set the content provider
		 */
		treeViewer.setContentProvider(new UniverseTreeContentProvider());

		/*
		 * Set the label provider
		 */
		treeViewer.setLabelProvider(new DecoratingLabelProvider(
				new UniverseTreeLabelProvider(),
				new UniverseDecoratorLabelProvider()));

		/*
		 * Set the model input
		 */
		treeViewer.setInput(Universe.createModelInput());

		/*
		 * Create the table viewer to show tree selection content
		 */
		tableViewer = new TableViewer(sash, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);

		/*
		 * Set the content provider
		 */
		tableViewer.setContentProvider(ArrayContentProvider.getInstance());

		/*
		 * Set the label provider
		 */
		tableViewer.setLabelProvider(new TableLabelProvider());

		/*
		 * Add support for D&D in the table viewer
		 */
		Transfer[] transferTypes = new Transfer[] { ElementsArrayDataTransfer
				.getInstance() };
		tableViewer.addDragSupport(DND.DROP_MOVE, transferTypes,
				new TableDragSourceListener(tableViewer));
		tableViewer.addDropSupport(DND.DROP_MOVE, transferTypes,
				new TableDropAdapter(tableViewer));

		/*
		 * Setup the table
		 */
		Table table = tableViewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		TableColumn column = new TableColumn(table, SWT.NONE);
		column.setText("Selection Content");
		column.setWidth(200);

		/*
		 * Add a selection listener to the tree viewer
		 */
		treeViewer.addSelectionChangedListener(new TreeSelectionChangeListener(
				tableViewer));

	}

	private static void createToolBar(final Shell shell) {
		/*
		 * Create the tool bar
		 */
		ToolBar bar = new ToolBar(shell, SWT.FLAT);

		/*
		 * Add items to the tool bar
		 */
		ToolItem item = new ToolItem(bar, SWT.CHECK);
		item.setImage(ImagesRegistry.getInstance().get(ImagesRegistry.ICN_SORT));
		item.setToolTipText("Sort selected elements.");
		item.setSelection(false);
		item.addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				ToolItem item = (ToolItem) event.widget;

				/*
				 * Enable/Disable sorter
				 */
				if (item.getSelection())
					treeViewer.setSorter(new TreeSorter());
				else
					treeViewer.setSorter(null);
				treeViewer.refresh();
			}
		});

		item = new ToolItem(bar, SWT.CHECK);
		item.setImage(ImagesRegistry.getInstance().get(
				ImagesRegistry.ICN_FILTER));
		item.setToolTipText("Filter empty elements.");
		item.setSelection(false);
		item.addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				ToolItem item = (ToolItem) event.widget;
				
				/*
				 * Enable/Disable filter
				 */
				if (item.getSelection())
					treeViewer.setFilters(new ViewerFilter[] { filter });
				else
					treeViewer.removeFilter(filter);
				treeViewer.refresh();
			}
		});

		bar.pack();
	}
}
